//
//  File.swift
//  File
//
//  Created by ellzu gu on 2021/9/6.
//

import Foundation
import EZFoundation_C

public class PacketHeader {
    
    public enum PacketType: UInt8 {
        case Unknow = 0
        case Map = 1 //Json
        case File = 2
    }
    
    public var version: UInt8
    public var headerCount: UInt8
    public var dataCount: UInt64
    public var identifier: UInt64
    public var type: PacketType
    
    public init(_ version: UInt8) {
        self.version = version
        self.headerCount = 1 + 1 + 8 + 8 + 1
        self.dataCount = 0
        self.identifier = 0
        self.type = .Unknow
    }
    
}

extension PacketHeader {
    static func header(_ version: UInt8) -> PacketHeader? {
        switch version {
        case 0x01:
            return PacketHeader(0x01)
        default:
            return nil
        }
    }
}

public extension PacketHeader {
    func copyBytes(to: UnsafeMutableRawPointer, rawCount: UInt64) {
        guard self.headerCount <= rawCount else {
            return
        }
        var storage = MakeUIntStorage(to)
        var formatter = MakeUIntStorageFormatter(1)
        formatter.replaceUInt8(&formatter, &storage, 0, version)
        formatter.replaceUInt8(&formatter, &storage, 1, headerCount)
        formatter.replaceUInt64(&formatter, &storage, 2, dataCount)
        formatter.replaceUInt64(&formatter, &storage, 10, identifier)
        formatter.replaceUInt8(&formatter, &storage, 18, type.rawValue)
    }
    
    func toData() -> Data {
        let count: UInt64 = UInt64(self.headerCount)
        let buffer = UnsafeMutableRawPointer.allocate(byteCount: Int(count), alignment: 0)
        self.copyBytes(to: buffer, rawCount: count)
        let data = Data(bytesNoCopy: buffer, count: Int(count), deallocator: .custom({_,_  in
            buffer.deallocate()
        }))
        return data
    }
}

extension PacketHeader {
    public static func header(_ data: Data) -> Result<PacketHeader, DispatchError> {
        data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Result<PacketHeader, DispatchError> in
            guard let buf = buffer.baseAddress else {
                return .failure(DispatchError(.NotEnoughBuffer))
            }
            return self.header(buf, bufCount: UInt64(buffer.count))
        }
    }
    
    public static func header(_ buf: UnsafeRawPointer, bufCount: UInt64) -> Result<PacketHeader, DispatchError> {
        guard bufCount > 1 else {
            return .failure(DispatchError(.NotEnoughBuffer))
        }
        var storage = MakeUIntStorage(buf)
        var formatter = MakeUIntStorageFormatter(1)
        guard let headInfo = header(formatter.readUInt8(&formatter, &storage, 0)) else {
            //不支持的版本
            return .failure(DispatchError(.UnsupportVersion))
        }
        guard bufCount >= headInfo.headerCount else {
            //这数据太短
            return .failure(DispatchError(.NotEnoughBuffer))
        }
        guard headInfo.headerCount == formatter.readUInt8(&formatter, &storage, 1) else {
            //校验失败，这不是一个TCPPacket
            return .failure(DispatchError(.FormatterError))
        }
        headInfo.dataCount = formatter.readUInt64(&formatter, &storage, 2)
        headInfo.identifier = formatter.readUInt64(&formatter, &storage, 10)
        headInfo.type = PacketType(rawValue: formatter.readUInt8(&formatter, &storage, 18)) ?? .Unknow
        return .success(headInfo)
    }
}
